//
// Created by edward on 22-11-16.
//

#include "test.h"
#include "Queue/Queue_v0.h"
#include "utils.h"
#include "activity.h"
#include "LockFreeStack.h"
#include "gtest/gtest.h"
#include <string>
#include <thread>
//#include <atomic>
#include <memory>
#include <tbb/concurrent_queue.h>

using namespace std;

namespace edward {
    namespace multithread {

        namespace {
            class A {
            public:
                int x_;
                A(int x = 0): x_(x) {
                    print(x_, "ctor");
                }
                ~A() {
                    print(x_, "dtor");
                }
            };
            TEST(LockFreeStack, logic) {
                LockFreeStack<A> lockFreeStack;
                lockFreeStack.push(1);
                lockFreeStack.push(2);
                lockFreeStack.push(3);

                shared_ptr<A> p;
                EXPECT_EQ(lockFreeStack.pop()->x_, 3);
                EXPECT_EQ(lockFreeStack.pop()->x_, 2);
                EXPECT_EQ(lockFreeStack.pop()->x_, 1);
            }

            TEST(tbb_concurrent_queue, basic_use) {
                tbb::concurrent_queue<int> q;
                q.push(1);
                q.push(2);
                q.push(3);

                int item;
                q.try_pop(item);
                EXPECT_EQ(item, 1);
                q.try_pop(item);
                EXPECT_EQ(item, 2);
                q.try_pop(item);
                EXPECT_EQ(item, 3);
            }
        }

        void test_produce_consume() {
            Queue<string> messageQueue;
            edward::print("test_produce_consume begin:");
            thread producer(produce<Queue<string>>, ref(messageQueue));
            thread consumer(consume<Queue<string>>, ref(messageQueue));
            producer.join();
            //不用等待processer，如果preparer结束，则直接推出进程
            return;
        }

        void test_atomic_lock_free() {
            //g++ (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0
            print("atomic_bool", "always? :", atomic_bool::is_always_lock_free);    //true
            print("atomic_bool", ":", atomic_bool().is_lock_free());    //true
            print("atomic_int", "always? :", atomic_int::is_always_lock_free);    //true
            print("atomic_int", ":", atomic_int().is_lock_free());    //true
            print("atomic_char", "always? :", atomic_char::is_always_lock_free);    //true
            print("atomic_char", ":", atomic_char().is_lock_free());    //true
            print("atomic<double>", "always? :", atomic<double>::is_always_lock_free);    //true
            print("atomic<double>", ":", atomic<double>().is_lock_free());    //true
            print("atomic<int*>", "always? :", atomic<int*>::is_always_lock_free);    //true
            print("atomic<int*>", ":", atomic<int*>().is_lock_free());    //true
            shared_ptr<int> p;
            print("atomic_shared_ptr", ":", atomic_is_lock_free(&p));    //false

            print("atomic<shared_ptr>", ":", std::atomic<std::shared_ptr<int>>().is_lock_free());    //false


        }

    }
}
